<script lang="ts">
import { Component, Vue, Prop, Watch } from 'vue-property-decorator'
import { CreateElement } from 'vue'
import InputNumberWithRatioUnit from './InputNumberWithRatioUnit.vue'

@Component({
  name: 'InputNumberWithRatio',
  components: { InputNumberWithRatioUnit }
})
export default class extends Vue {
  @Prop({ type: [String, Number, Array] })
  private value!: string | number | Array<string | number>
  // input type
  @Prop({
    type: String,
    required: false,
    default: 'number',
    validator: v => ['number', 'numberrange'].includes(v)
  })
  private type!: string
  // conversion ratio
  @Prop({ type: Number, required: false, default: 1 })
  private ratio!: number
  // display precision
  @Prop({ type: Number, required: false, default: 9 })
  private precision!: number
  // range separator
  @Prop({ type: String, required: false, default: '-' })
  private rangeSeparator!: string

  private valueStart: string | number = ''
  private valueEnd: string | number = ''

  get bindRatio () {
    return typeof this.ratio === 'number' ? this.ratio : 1
  }
  get bindPrecision () {
    return typeof this.precision === 'number' ? this.precision : 9
  }

  @Watch('value', { deep: true, immediate: true })
  private onValueChange (val: any, oldVal: any) {
    if (this.type === 'numberrange') {
      if (
        val instanceof Array &&
        JSON.stringify(val) !== JSON.stringify([this.valueStart, this.valueEnd])
      ) {
        this.valueStart = val[0]
        this.valueEnd = val[1]
      }

      if (val === undefined) {
        this.valueStart = ''
        this.valueEnd = ''
      }
    }
  }

  render (h: CreateElement) {
    if (this.type === 'number') {
      return h('InputNumberWithRatioUnit', {
        attrs: this.$attrs,
        props: {
          ...this.$attrs,
          value: this.value,
          ratio: this.ratio === null ? 1 : this.ratio,
          precision: this.precision === null ? 9 : this.precision
        },
        on: {
          ...this.$listeners,
          input: (v: string | number) => {
            this.$emit('input', v)
          }
        }
      })
    } else {
      return h(
        'div',
        {
          class: 'input-number-range-with-ratio',
          on: {
            change: () => {
              this.$emit('change', this.value)
            }
          }
        },
        [
          h('InputNumberWithRatioUnit', {
            attrs: this.$attrs,
            props: {
              ...this.$attrs,
              value: this.valueStart,
              ratio: this.bindRatio,
              precision: this.bindPrecision
            },
            on: {
              input: (v: string | number) => {
                this.valueStart = v

                if (
                  typeof v === 'number' &&
                  typeof this.valueEnd === 'number' &&
                  v > this.valueEnd
                ) {
                  this.valueStart = this.valueEnd
                }

                let val =
                  typeof this.valueStart === 'number' &&
                  typeof this.valueEnd === 'number'
                    ? [this.valueStart, this.valueEnd]
                    : null
                this.$emit('input', val)
              }
            }
          }),
          h(
            'span',
            { class: 'input-number-range-separator' },
            this.rangeSeparator
          ),
          h('InputNumberWithRatioUnit', {
            attrs: this.$attrs,
            props: {
              ...this.$attrs,
              value: this.valueEnd,
              ratio: this.bindRatio,
              precision: this.bindPrecision
            },
            on: {
              input: (v: string | number) => {
                this.valueEnd = v

                if (
                  typeof v === 'number' &&
                  typeof this.valueStart === 'number' &&
                  v < this.valueStart
                ) {
                  this.valueEnd = this.valueStart
                }

                let val =
                  typeof this.valueStart === 'number' &&
                  typeof this.valueEnd === 'number'
                    ? [this.valueStart, this.valueEnd]
                    : null
                this.$emit('input', val)
              }
            }
          })
        ]
      )
    }
  }
}
</script>

<style lang="scss" scoped>
.input-number-range-with-ratio {
  display: flex;
  align-items: center;
  > .input-number-range-separator {
    padding: 0 5px;
  }
}
</style>
